package cz.muni.fi.hauntedhouses;

import java.util.ArrayList;
import java.util.List;
import javax.ejb.Local;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;


/**
 *
 * @author Martin Vala, 359917
 */
@Stateless
public class HumanDAO implements HumanDAOLocal {
    
    @PersistenceContext
    private EntityManager em;

    public void setEntityManager(EntityManager em) {
        this.em = em;
    }
    
    private EntityManager getEntityManager() {
        if(em == null) {
            throw new NullPointerException("EntityManager is null");
        }
        return em;
    }

    @Override
    public void create(HumanTO humanTo) {
        if (humanTo == null || humanTo.getId() != null) {
            throw new IllegalArgumentException("Human is null or human's ID is not null");
        }
        Human human = HumanTO.TOToEntity(humanTo);
        
        em = getEntityManager();
        em.persist(human);
        humanTo.setId(human.getId());
    }

    @Override
    public void update(HumanTO humanTo) {
        if (humanTo == null || humanTo.getId() == null || humanTo.getId() < 1) {
            throw new IllegalArgumentException("Human is null or wrong ID format");
        }
        Human human = HumanTO.TOToEntity(humanTo);
        
        em = getEntityManager();
        if (em.find(Human.class, human.getId()) == null) {
            throw new IllegalArgumentException("Given human not found");
        }
        em.merge(human);
    }

    @Override
    public void remove(HumanTO humanTo) {
        if (humanTo == null || humanTo.getId() == null || humanTo.getId() < 1) {
            throw new IllegalArgumentException("Human is null or wrong ID format");
        }
        
        em = getEntityManager();     
        Human h = em.find(Human.class, humanTo.getId());
        if (h == null) {
            throw new IllegalArgumentException("Given human not found");
        }
        em.remove(h);
    }

    @Override
    public HumanTO get(Long id) {
        if (id == null || id < 1) {
            throw new IllegalArgumentException("ID is null or wrong format");
        }
        em = getEntityManager();
        Human human = em.find(Human.class, id);
        if (human == null) {
            throw new IllegalArgumentException("Human with given ID not found");
        }       
        HumanTO humanTo = HumanTO.entityToTO(human);        
        return humanTo;
    }

    @Override
    public List<HumanTO> findAll() {
        em = getEntityManager();
        TypedQuery<Human> query = em.createQuery("SELECT h FROM Human h", Human.class);
        List<Human> results = query.getResultList();
        if (results.isEmpty()) {
            return null;
        }
        List<HumanTO> humans = new ArrayList<HumanTO>();
        for (Human h : results) {
            humans.add(HumanTO.entityToTO(h));
        }
        return humans;
    }

    @Override
    public List<HumanTO> findByName(String name) {
        if (name == null) {
            throw new IllegalArgumentException("Name is null");
        }
        em = getEntityManager();
        TypedQuery<Human> query = em.createQuery("SELECT h FROM Human h WHERE name = :name", Human.class);
        List<Human> results = query.setParameter("name", name).getResultList();
        if (results.isEmpty()) {
            return null;
        }
        List<HumanTO> humans = new ArrayList<HumanTO>();
        for (Human h : results) {
            humans.add(HumanTO.entityToTO(h));
        }
        return humans;
    }

    @Override
    public List<HumanTO> findByWorstFear(Fear worstFear) {
        if (worstFear == null) {
            throw new IllegalArgumentException("Worst fear is null");
        }
        em = getEntityManager();
        TypedQuery<Human> query = em.createQuery("SELECT h FROM Human h WHERE worstFear = :worstFear", Human.class);
        List<Human> results = query.setParameter("worstFear", worstFear).getResultList();
        if (results.isEmpty()) {
            return null;
        }
        List<HumanTO> humans = new ArrayList<HumanTO>();
        for (Human h : results) {
            humans.add(HumanTO.entityToTO(h));
        }
        return humans;
    }


    @Override
    public List<HumanTO> findByResistence(int resistance) {
        em = getEntityManager();
        TypedQuery<Human> query = em.createQuery("SELECT h FROM Human h WHERE resistance = :resistance", Human.class);
        List<Human> results = query.setParameter("resistance", (float) resistance).getResultList();
        if (results.isEmpty()) {
            return null;
        }
        List<HumanTO> humans = new ArrayList<HumanTO>();
        for (Human h : results) {
            humans.add(HumanTO.entityToTO(h));
        }
        return humans;
    }

    @Override
    public List<HumanTO> findByGender(Gender gender) {
        if (gender == null) {
            throw new IllegalArgumentException("Gender is null");
        }
        em = getEntityManager();
        TypedQuery<Human> query = em.createQuery("SELECT h FROM Human h WHERE gender = :gender", Human.class);
        List<Human> results = query.setParameter("gender", gender).getResultList();
        if (results.isEmpty()) {
            return null;
        }
        List<HumanTO> humans = new ArrayList<HumanTO>();
        for (Human h : results) {
            humans.add(HumanTO.entityToTO(h));
        }
        return humans;
    }
    
}
